package com.cxs.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cxs.common.dto.NodeDto;
import com.cxs.common.exception.APIException;
import com.cxs.controller.base.BaseController;
import com.cxs.entity.Role;
import com.cxs.entity.RolePerm;
import com.cxs.entity.UserRole;
import com.cxs.service.IRolePermService;
import com.cxs.service.IRoleService;
import com.cxs.service.IUserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author chaoxiaoshu
 * @since 2022-06-08
 */
@Slf4j
@RestController
@RequestMapping("/sys/role")
public class RoleController extends BaseController {

    @Autowired
    IRoleService roleService;

    @Autowired
    IUserRoleService userRoleService;

    @Autowired
    IRolePermService rolePermService;

    @PreAuthorize("hasAuthority('sys:role:list')")
    @PostMapping("/page")
    public IPage<Role> page(@RequestBody Map<String, Integer> paramsMap) {
        long current = 1L;
        long size = 10L;
        if (paramsMap.size() > 0) {
            if (paramsMap.containsKey("current")) {
                current = paramsMap.get("current");
            }
            if (paramsMap.containsKey("size")) {
                size = paramsMap.get("size");
            }
        }
        IPage<Role> page = roleService.page(new Page<>(current, size));
        return page;
    }

    @GetMapping("/list")
    public List<Role> list() {
        return roleService.list();
    }



    /**
     * 获取指定角色信息
     * @param id
     * @return
     */
    @GetMapping("/info/{id}")
    public Map<String, Object> getRoleInfo(@PathVariable Long id) {
        Map<String, Object> map = new HashMap<>();
        Role role = roleService.getById(id);
        List<Integer> menuIds = roleService.findPermissionIdsByRoleId(id);
        map.put("role", role);
        map.put("menuIds", menuIds);
        return map;
    }

    /**
     * 获取全部权限的树形数据
     * @return
     */
    @GetMapping("/nodes")
    public List<NodeDto> getNodes() {
        return permissionService.getNodes();
    }


    /**
     * 分配权限
     * @param id 角色id
     * @param menuIds 权限id列表
     * @return
     */
    @Transactional
    @PreAuthorize("hasAuthority('sys:role:perm')")
    @PostMapping("/perm/{id}")
    public List<Long> updatePerm(@PathVariable long id, @RequestBody List<Long> menuIds) {
        // 删除所有该角色的权限
        rolePermService.remove(new QueryWrapper<RolePerm>().eq("role_id", id));
        List<RolePerm> rolePerms = new ArrayList<>();
        menuIds.forEach(menuId -> rolePerms.add(new RolePerm(id, menuId)));
        // 批量添加
        rolePermService.saveBatch(rolePerms);
        // 清除角色关联的缓存
        permissionService.clearCacheByRoleId(id);
        return menuIds;
    }

    /**
     * 新增角色
     * @param r
     * @return
     */
    @Transactional
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:role:save')")
    public Role save(@RequestBody Role r) {
        Role role = roleService.createRole(r);
        boolean result = roleService.save(role);
        if (!result) {
            throw new APIException("A0001");
        }
        return role;
    }

    /**
     * 更新角色
     * @param r
     * @return
     */
    @Transactional
    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:role:update')")
    public Role update(@RequestBody Role r) {
        Role role = roleService.createRole(r);
        boolean result = roleService.updateById(role);
        if (!result) {
            throw new APIException("A0001");
        }
        permissionService.clearCacheByRoleId(role.getId());
        return role;
    }

    /**
     * 删除角色
     * @param ids
     * @return
     */
    @Transactional
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('sys:role:delete')")
    public String delete(@RequestBody Long[] ids){
        roleService.removeByIds(Arrays.asList(ids));
        // 同步删除
        rolePermService.remove(new QueryWrapper<RolePerm>().in("role_id", ids));
        userRoleService.remove(new QueryWrapper<UserRole>().in("role_id", ids));
        for (Long id : ids) {
            permissionService.clearCacheByRoleId(id);
        }
        return "";
    }
}
